using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.StateMachine.SPI;

namespace T.FAS.Runtime.StateMachine.Engine
{
    internal class ExpressionActionProcess : IActionProcess
    {
        public const string CSTKEY = "FAS.Expression.Action";
        private const string contextName = "FASContext";
        public string Key => CSTKEY;

        public string Description => "表达式计算";

        public List<ParamInfo> NeedParamInfo =>null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="record"></param>
        /// <param name="action"></param>
        /// <param name="metadata"></param>
        /// <param name="extParams">特殊参数，包括待注入到表达式中的ChangeSet变量</param>
        /// <returns></returns>
        public TRecord Do(TRecord record, TAction action, StateMachineMetadata metadata, Dictionary<string, object> extParams = null)
        {
            if (record == null || action == null)
                return record;
            var i18NDecription = I18NUtil.GetTranslatedText(action.GetRefSchemaExpr(metadata), action.Name ?? action.Description);
            if (!string.IsNullOrEmpty(action.Target))
            {
                var target = action.Target;
                if (record.GetDynamicMemberNames().Contains(target, StringComparer.OrdinalIgnoreCase) == false)
                    throw new Exception(CommonStringClass.ExpressionActionProcess_Do + target);
                var data = record.GetValue(target);
                if (data == null)
                    return record;

                Dictionary<string, object> expParam;
                if (action.Paramters != null)
                    expParam = new Dictionary<string, object>(action.Paramters);
                else
                    expParam = new Dictionary<string, object>();

                var fasContext = new FASContext
                {
                    CurrentRecord = record,
                    PKColumnName = record.PKColumnName,
                };

                var result = Expression.Service.ExprService.GetInstance.Execute(action.ActionInfoJson, fasContext, expParam);
                if (result.State == Expression.Entity.ResultState.Fail)
                    throw new Exception("StateMachine.Action " + i18NDecription + CommonStringClass.ExpressionActionProcess_ExprExecError + result.ErrMsg);
                else
                    record.SetValue(target, result.Result);

                return record;
            }
            else
            {
                Dictionary<string, object> expParam;
                if (action.Paramters != null)
                    expParam = new Dictionary<string, object>(action.Paramters);
                else
                    expParam = new Dictionary<string, object>();

                var fasContext = new FASContext
                {
                    CurrentRecord = record,
                    PKColumnName = record.PKColumnName
                };

                //LocalLogService.Write(new { info = "状态机表达式执行前", cdo = metadata?.Code, content = record.GetTRecordDebugInfos() });
                var result = Expression.Service.ExprService.GetInstance.Execute(action.ActionInfoJson, fasContext, expParam);
                //LocalLogService.Write(new { info = "状态机表达式执行后", cdo = metadata?.Code, content = record.GetTRecordDebugInfos() });

                if (result.State == Expression.Entity.ResultState.Fail)
                    throw new Exception("StateMachine.Action " + i18NDecription + CommonStringClass.ExpressionActionProcess_ExprExecError + result.ErrMsg);
                return record;
            }
        }

        private TChangeSet GetExtParams(Dictionary<string, object> extParams)
        {
            if (extParams == null) return null;
            if (!extParams.ContainsKey("ChangeSet")) return null;
            else return extParams["ChangeSet"] as TChangeSet;
        }
    }
}
